<!DOCTYPE html>
<html>
<head>
    <title>音频文件识别工具</title>
    <meta charset="UTF-8">
    <style>
        body { 
            font-family: Arial, sans-serif; 
            margin: 20px; 
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        h1 { color: #333; }
        button { 
            padding: 10px 20px; 
            background-color: #4CAF50; 
            border: none; 
            color: white; 
            cursor: pointer;
            border-radius: 5px;
            font-size: 16px;
            margin: 5px;
        }
        button:hover { background-color: #45a049; }
        button:disabled { background-color: #cccccc; }
        
        #resultText { 
            margin-top: 20px; 
            padding: 10px; 
            border: 1px solid #ddd; 
            min-height: 100px;
            border-radius: 5px;
            white-space: pre-wrap;
            background-color: white;
            color: #333;
            font-family: inherit;
            font-size: inherit;
            width: 100%;
            box-sizing: border-box;
            resize: vertical;
        }
        
        .settings {
            margin: 20px 0;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            background-color: #f9f9f9;
        }
        
        .settings label {
            display: block;
            margin: 10px 0 5px 0;
        }
        
        .settings input, .settings select {
            padding: 5px;
            width: 100%;
            box-sizing: border-box;
            margin-bottom: 10px;
        }
        
        .copy-btn {
            padding: 5px 10px;
            font-size: 12px;
            margin-top: 5px;
            background-color: #f0f0f0;
            color: #333;
            border: 1px solid #ddd;
        }
        
        .copy-btn:hover {
            background-color: #e0e0e0;
        }
        
        .info-box {
            margin: 10px 0;
            padding: 10px;
            border-radius: 5px;
            background-color: #e7f3fe;
            border-left: 6px solid #2196F3;
        }
        
        .success-box {
            background-color: #ddffdd;
            border-left: 6px solid #4CAF50;
        }
        
        .error-box {
            background-color: #ffdddd;
            border-left: 6px solid #f44336;
        }
        
        .history-container {
            margin-top: 20px;
            max-height: 300px;
            overflow-y: auto;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 10px;
        }
        
        .history-item {
            padding: 5px;
            border-bottom: 1px solid #eee;
        }
        
        .history-item:last-child {
            border-bottom: none;
        }
        
        #loadingSpinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3498db;
            border-radius: 50%;
            width: 20px;
            height: 20px;
            animation: spin 2s linear infinite;
            margin-left: 10px;
            display: none;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .file-upload {
            background-color: #f8f9fa;
            border: 1px dashed #ced4da;
            border-radius: 5px;
            padding: 20px;
            text-align: center;
            margin: 10px 0;
            position: relative;
        }
        
        .file-upload:hover {
            background-color: #e9ecef;
        }
        
        .file-info {
            margin-top: 10px;
            font-size: 14px;
            color: #6c757d;
        }
    </style>
</head>
<body>
    <h1>音频文件识别工具</h1>
    <div class="info-box">
        <strong>说明:</strong> 上传音频文件（如 .wav, .mp3, .flac 文件）进行语音识别。支持多种语言的自动识别。
        <ul>
            <li>支持文件格式：WAV, MP3, FLAC, OGG, M4A 等常见音频格式</li>
            <li>最大文件大小：通常不超过50MB的文件效果最佳</li>
            <li>语言支持：中文, 英语, 粤语, 日语, 韩语和自动检测</li>
        </ul>
    </div>
    
    <div class="settings">
        <h3>上传音频文件</h3>
        
        <div class="file-upload" id="dropZone">
            <input type="file" id="audioFile" accept="audio/*" onchange="updateFileInfo()">
            <p>点击选择或拖放音频文件到此处</p>
            <div class="file-info" id="fileInfo">未选择文件</div>
        </div>
        
        <h3>识别设置</h3>
        <label for="language">语言:</label>
        <select id="language">
            <option value="auto" selected>自动检测 (auto)</option>
            <option value="zh">中文 (zh)</option>
            <option value="en">英语 (en)</option>
            <option value="yue">粤语 (yue)</option>
            <option value="ja">日语 (ja)</option>
            <option value="ko">韩语 (ko)</option>
            <option value="nospeech">无语音 (nospeech)</option>
        </select>
        
        <label for="useItn">使用 ITN (逆文本标准化):</label>
        <select id="useItn">
            <option value="true" selected>是</option>
            <option value="false">否</option>
        </select>
        
        <label for="batchSize">批处理大小 (秒):</label>
        <input type="number" id="batchSize" value="60" min="1" max="300">
        
        <label for="mergeVad">合并VAD结果:</label>
        <select id="mergeVad">
            <option value="true" selected>是</option>
            <option value="false">否</option>
        </select>
        
        <label for="mergeLength">合并长度 (秒):</label>
        <input type="number" id="mergeLength" value="15" min="1" max="60">
        
        <button id="recognizeBtn" onclick="recognizeAudio()">开始识别</button>
        <span id="loadingSpinner" style="display: none;"></span>
    </div>
    
    <div>
        <h3>识别结果: <button onclick="copyResult()" class="copy-btn">复制结果</button></h3>
        <textarea id="resultText" readonly>等待识别结果...</textarea>
    </div>
    
    <div>
        <h3>历史记录:</h3>
        <button onclick="clearHistory()" style="padding: 5px; font-size: 12px;">清除历史</button>
        <div id="historyContainer" class="history-container">
            <!-- 历史记录将在这里显示 -->
        </div>
    </div>
    
    <script>
        let recognitionHistory = [];
        
        // 添加拖放功能
        const dropZone = document.getElementById('dropZone');
        
        dropZone.addEventListener('dragover', (e) => {
            e.preventDefault();
            dropZone.style.backgroundColor = '#e9ecef';
        });
        
        dropZone.addEventListener('dragleave', (e) => {
            e.preventDefault();
            dropZone.style.backgroundColor = '#f8f9fa';
        });
        
        dropZone.addEventListener('drop', (e) => {
            e.preventDefault();
            dropZone.style.backgroundColor = '#f8f9fa';
            
            if (e.dataTransfer.files.length) {
                const audioFile = document.getElementById('audioFile');
                audioFile.files = e.dataTransfer.files;
                updateFileInfo();
            }
        });
        
        function updateFileInfo() {
            const fileInput = document.getElementById('audioFile');
            const fileInfo = document.getElementById('fileInfo');
            
            if (fileInput.files.length > 0) {
                const file = fileInput.files[0];
                const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
                fileInfo.innerHTML = `文件名: ${file.name}<br>大小: ${fileSizeMB} MB<br>类型: ${file.type}`;
            } else {
                fileInfo.innerHTML = '未选择文件';
            }
        }
        
        async function recognizeAudio() {
            const audioFile = document.getElementById('audioFile');
            
            if (audioFile.files.length === 0) {
                showMessage('请选择一个音频文件', 'error');
                return;
            }
            
            const file = audioFile.files[0];
            const language = document.getElementById('language').value;
            const useItn = document.getElementById('useItn').value === 'true';
            const batchSize = document.getElementById('batchSize').value;
            const mergeVad = document.getElementById('mergeVad').value === 'true';
            const mergeLength = document.getElementById('mergeLength').value;
            
            // 显示加载动画
            document.getElementById('loadingSpinner').style.display = 'inline-block';
            document.getElementById('recognizeBtn').disabled = true;
            document.getElementById('resultText').value = '正在识别中...';
            
            try {
                const formData = new FormData();
                formData.append('audio_file', file);
                formData.append('language', language);
                formData.append('use_itn', useItn);
                formData.append('batch_size_s', batchSize);
                formData.append('merge_vad', mergeVad);
                formData.append('merge_length_s', mergeLength);
                
                const startTime = new Date();
                
                const response = await fetch('/funasr/transcribe', {
                    method: 'POST',
                    body: formData
                });
                
                const endTime = new Date();
                const processingTime = (endTime - startTime) / 1000;
                
                if (!response.ok) {
                    const errorData = await response.json();
                    throw new Error(errorData.detail || '识别请求失败');
                }
                
                const result = await response.json();
                
                // 显示识别结果
                document.getElementById('resultText').value = result.text;
                
                // 添加到历史记录
                addToHistory(file.name, result.text, result.duration, processingTime);
                
                showMessage(`识别成功！处理时间: ${processingTime.toFixed(2)}秒，推理时间: ${result.duration.toFixed(2)}秒`, 'success');
                
            } catch (error) {
                document.getElementById('resultText').value = `识别失败: ${error.message}`;
                showMessage(`识别失败: ${error.message}`, 'error');
            } finally {
                // 隐藏加载动画
                document.getElementById('loadingSpinner').style.display = 'none';
                document.getElementById('recognizeBtn').disabled = false;
            }
        }
        
        function showMessage(message, type = 'info') {
            const existingMsg = document.querySelector('.message-box');
            if (existingMsg) {
                existingMsg.remove();
            }
            
            // 增强错误信息的用户友好程度
            if (type === 'error') {
                if (message.includes('413') || message.includes('负载')) {
                    message = '文件太大，请使用小于50MB的文件，或考虑压缩音频。';
                } else if (message.includes('format') || message.includes('格式')) {
                    message = '音频格式不受支持，请尝试使用WAV, MP3或FLAC格式。';
                } else if (message.includes('transcription') || message.includes('识别')) {
                    message = '识别过程中出错，可能是音频内容不够清晰，请检查音频质量。';
                }
            }
            
            const msgBox = document.createElement('div');
            msgBox.className = `info-box ${type}-box message-box`;
            msgBox.innerHTML = message;
            
            const settings = document.querySelector('.settings');
            settings.parentNode.insertBefore(msgBox, settings.nextSibling);
            
            // 5秒后自动消失
            setTimeout(() => {
                if (msgBox.parentNode) {
                    msgBox.remove();
                }
            }, 5000);
        }
        
        function addToHistory(fileName, text, inferenceTime, totalTime) {
            const currentTime = new Date().toLocaleTimeString();
            
            recognitionHistory.push({
                time: currentTime,
                file: fileName,
                text: text,
                inference_time: inferenceTime,
                total_time: totalTime
            });
            
            updateHistoryDisplay();
        }
        
        function updateHistoryDisplay() {
            const historyContainer = document.getElementById('historyContainer');
            historyContainer.innerHTML = '';
            
            // 显示最近的5条记录
            const recentHistory = recognitionHistory.slice(-5).reverse();
            
            for (const item of recentHistory) {
                const historyItem = document.createElement('div');
                historyItem.className = 'history-item';
                
                let infoText = `<strong>${item.time}</strong> [文件: ${item.file}]<br>${item.text}`;
                if (item.inference_time) {
                    infoText += `<br><small>推理时间: ${item.inference_time.toFixed(2)}秒, 总处理时间: ${item.total_time.toFixed(2)}秒</small>`;
                }
                
                historyItem.innerHTML = infoText;
                historyContainer.appendChild(historyItem);
            }
        }
        
        function clearHistory() {
            recognitionHistory = [];
            updateHistoryDisplay();
        }
        
        function copyResult() {
            const resultText = document.getElementById('resultText');
            resultText.select();
            document.execCommand('copy');
            showMessage('已复制识别结果到剪贴板', 'success');
        }
    </script>
</body>
</html>
